/*
 * Copyright 2012 XueSong Guo.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package wbbs.service;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import wbbs.domain.Reply;
import wbbs.domain.Topic;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

@Singleton
public class TopicService {

    @Inject
    BoardService boardService;

    @Inject
    QueryRunner qr;

    final Map<Integer, Integer> topicReplyCountMap = new HashMap<Integer, Integer>();

    public PaginatedList<Topic> listBoardTopic(int board, int page, int pageSize) throws SQLException {
        int count = boardService.getBoardTopicCount(board);
        PaginatedList<Topic> list = new PaginatedList<Topic>(pageSize);
        list.setItemCount(count);
        list.setPage(page);
        list.addAll(qr.query("select * from Topic where boardId=? order by updateDate desc limit ? offset ?",
                new BeanListHandler<Topic>(Topic.class), board, list.getPageSize(), list.getOffset()));
        return list;
    }

    public void insertTopic(Topic topic) throws SQLException {
        Connection con = qr.getDataSource().getConnection();
        try {
            qr.update(con, "insert into Topic(boardId, authorId, title, content, postDate, updateDate) values(?, ?, ?, ?, ?, ?)",
                    topic.boardId, topic.authorId, topic.title, topic.content, topic.postDate, topic.updateDate);
            topic.id = qr.query(con, "call identity()", new ScalarHandler<Number>()).intValue();
        } finally {
            con.close();
        }
        boardService.changeBoardTopicCount(topic.boardId, 1);
    }

    public Topic findTopic(int id) throws SQLException {
        return qr.query("select * from Topic where id=?", new BeanHandler<Topic>(Topic.class), id);
    }

    public void updateTopic(Topic topic) throws SQLException {
        qr.update("update Topic set title=?, content=? where id=?",
                topic.title, topic.content, topic.id);
    }

    public void insertReply(int boardId, Reply reply) throws SQLException {
        Connection con = qr.getDataSource().getConnection();
        try {
            qr.update(con, "insert into Reply(topicId, authorId, content, postDate) values(?, ?, ?, ?)",
                    reply.topicId, reply.authorId, reply.content, reply.postDate);
            reply.id = qr.query(con, "call identity()", new ScalarHandler<Number>()).intValue();
        } finally {
            con.close();
        }
        boardService.changeBoardReplyCount(boardId, 1);
    }

    public void updateReply(Reply reply) throws SQLException {
        qr.update("update Reply set content=? where id=?", reply.content, reply.id);
    }

    public void updateReplyDelFlag(int replyId, boolean del) throws SQLException {
        qr.update("update Reply set del=? where id=?", del, replyId);
    }

    public int countTopicReply(int topic) throws SQLException {
        synchronized (topicReplyCountMap) {
            Integer count = topicReplyCountMap.get(topic);
            if (count == null) {
                count = qr.query("select count(*) from Reply where topicId=?", new ScalarHandler<Number>(), topic).intValue();
                topicReplyCountMap.put(topic, count);
            }
            return count;
        }
    }

    public PaginatedList<Reply> listReply(int topic, int page, int pageSize) throws SQLException {
        int count = countTopicReply(topic);
        PaginatedList<Reply> list = new PaginatedList<Reply>(pageSize);
        list.setItemCount(count);
        list.setPage(page);
        list.addAll(qr.query("select * from Reply where topicId=? order by id limit ? offset ?",
                new BeanListHandler<Reply>(Reply.class), topic, list.getPageSize(), list.getOffset()));
        return list;
    }
}
